package com.wno704.intf.controller;

import com.alibaba.fastjson2.JSONObject;
import com.wno704.intf.entity.IntfLog;
import com.wno704.intf.entity.IntfScript;
import com.wno704.intf.event.LogEvent;
import com.wno704.intf.service.IntfScriptService;
import com.wno704.system.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

/*
 * @Description: 接口进入类
 * @Author: wno704
 * @Date: 2023/11/25
 */
@Controller
@Slf4j
public class IntfController {

    @Autowired
    IntfScriptService intfScriptService;

    @RequestMapping("/**")
    public void runPostJson(HttpServletRequest request, HttpServletResponse response,
                            @RequestBody(required = false) String msg) {
        String uri = request.getRequestURI();
        String method = request.getMethod();
        String msgId = UUID.randomUUID().toString().trim().replaceAll("-", "");
        String startTime = DateUtil.formatNowDate("yyyy-MM-dd HH:mm:ss:SSS");
        String ipAddr = IPUtil.getIpAddr(request);

        ApplicationContext applicationContext = SpringContextUtil.getApplicationContext();

        Map<String, Object> reqHeaders = new HashMap<>();
        Enumeration headers = request.getHeaderNames();
        while (headers.hasMoreElements()) {
            String headerName = (String) headers.nextElement();
            String headerValue = request.getHeader(headerName);
            reqHeaders.put(headerName, headerValue);
        }
        Map<String, String> reqParam = RequestUtil.getParam(request);
        log.info("接口请求信息(msgId-{}) method:{},  uri:{}, reqHeaders:{}, reqParam:{}", msgId, method, uri, reqHeaders, msg);

        String[] name = new String[]{"$reqHeaders", "$reqParam", "$method", "$uri", "$msgId", "$httpServletRequest", "$httpServletResponse", "$queryParams", "$ipAddr"};
        Object[] param = new Object[]{reqHeaders, msg, method, uri, msgId, request, response, reqParam, ipAddr};

        IntfScript intf = intfScriptService.getScript(method, uri);

        if (ObjectUtils.isEmpty(intf)) {
            Map<String, Object> repHeaders = new HashMap<>();
            repHeaders.put("Content-Type", "application/json; charset=utf-8");
            response.setStatus(500);
            log.info("接口响应信息(msgId-{}) repStatus:{}, repHeaders:{}, repMsg:{}", msgId, 500, repHeaders, "请求路径或者方法错误。");
            createServletResponse(response, repHeaders, "{\"msg\": \"请求路径或者方法错误。\",\"code\": 500}");
            return;
        }
        IntfLog intfLog = new IntfLog();
        if (intf.getIsLog().equals(IntfScript.logStatus.SAVE.getValue())){
            intfLog.setLogId(msgId);
            intfLog.setIntfId(intf.getIntfId());
            intfLog.setMethod(intf.getMethod());
            intfLog.setUrl(intf.getUrl());
            intfLog.setRemark(intf.getRemark());
            intfLog.setRequestHeaders(JSONObject.toJSONString(reqHeaders));
            intfLog.setRequestIpAddr(ipAddr);
            intfLog.setRequestMsg(msg);
            intfLog.setRequestParam(JSONObject.toJSONString(reqParam));
            intfLog.setRequestTime(startTime);
            applicationContext.publishEvent(new LogEvent(intfLog,0));
        }

        Map<String, Object> rep = null;
        try {
            rep = (Map<String, Object>) GroovyUtil.executeGroovys(GroovyUtil.parseClass(intf.getScript()), name, param);
        }catch (Exception e){
            Map<String, Object> repHeaders = new HashMap<>();
            repHeaders.put("Content-Type", "application/json; charset=utf-8");
            response.setStatus(501);
            log.info("接口响应信息(msgId-{}) repStatus:{}, repHeaders:{}, repMsg:{}, errMsg:{}", msgId, 501, repHeaders, "内部错误，请联系管理员。", e.getMessage());
            createServletResponse(response, repHeaders, "{\"msg\": \"内部错误，请联系管理员。\",\"code\": 501}");
            return;
        }

        Map<String, Object> repHeaders = (Map<String, Object>) rep.get("repHeaders");
        int repStatus = (int) rep.get("repStatus");
        String repMsg = (String) rep.get("repMsg");

        log.info("接口响应信息(msgId-{}) repStatus:{}, repHeaders:{}, repMsg:{}", msgId, repStatus, repHeaders, repMsg);

        if (intf.getIsLog().equals(IntfScript.logStatus.SAVE.getValue())){
            String endTime = DateUtil.formatNowDate("yyyy-MM-dd HH:mm:ss:SSS");
            intfLog.setResponseHeaders(JSONObject.toJSONString(repHeaders));
            intfLog.setResponseMsg(repMsg);
            intfLog.setResponseStatus(repStatus+"");
            intfLog.setResponseTime(endTime);
            applicationContext.publishEvent(new LogEvent(intfLog,1));
        }
        response.setStatus(repStatus);
        createServletResponse(response, repHeaders, repMsg);
    }

    private void createServletResponse(HttpServletResponse response, Map<String, Object> header, String msg) {
        for (String key : header.keySet()) {
            response.setHeader(key, (String) header.get(key));
        }
        try {
            PrintWriter writer = response.getWriter();
            writer.write(msg);
            writer.close();
        } catch (IOException e) {
            log.error("集团规范接口同步响应异常", e);
        }
    }

}
